﻿using System;
using System.IO;
using System.Xml;
using System.Linq;
using System.Xaml;
using System.Text;
using System.Collections.Generic;
using System.Activities;
using System.Activities.XamlIntegration;

namespace Vision.Core.Components
{
    public class ActivityCatalog : IDisposable
    {
        private EnterpriseServicesDb DataAccess { get; set; }
                
        /// <summary>
        /// 
        /// </summary>
        /// <param name="catalogConnectionString"></param>
        public ActivityCatalog(string catalogConnectionString)
        {
            this.DataAccess = new EnterpriseServicesDb(catalogConnectionString);            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Entities.Config.Settings GetSettings()
        {
            Entities.Config.Settings settings = new Entities.Config.Settings();
            foreach (var item in this.DataAccess.Settings){
                settings.Add(item.Name, item.Value);    
            }            
            return settings;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Entities.Filing.Folder GetFolders()
        {
            Entities.Filing.Folder folder = new Entities.Filing.Folder();
            var folderRecord = (from a in this.DataAccess.Folders where a.FolderId == 0 select a).Single();
            if (folderRecord != null){
                folder.Id = folderRecord.FolderId;
                folder.Name = folderRecord.Name;
                folder.Folders = this.GetFolderChildren(folderRecord);
                folder.Activities = this.GetVisionActivities(folderRecord.FolderId);
                folder.Documents = this.GetVisionDocuments(folderRecord.FolderId);
            }
            return folder;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public Entities.Filing.Folder GetFolderById(int Id, bool includeChildren)
        {
            Entities.Filing.Folder folder = new Entities.Filing.Folder();
            var folderRecord = (from a in this.DataAccess.Folders where a.FolderId == Id select a).Single();
            if (folderRecord != null){
                folder.Id = folderRecord.FolderId;
                folder.Name = folderRecord.Name;
                folder.Folders = new List<Entities.Filing.Folder>();
                if (includeChildren){
                    folder.Folders = this.GetFolderChildren(folderRecord);
                }
                folder.Activities = this.GetVisionActivities(folderRecord.FolderId);
                folder.Documents = this.GetVisionDocuments(folderRecord.FolderId);
            }
            return folder;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="folderRecord"></param>
        /// <returns></returns>
        private List<Entities.Filing.Folder> GetFolderChildren(Entities.DataAccess.Folder folderRecord)
        {
            List<Entities.Filing.Folder> folders = new List<Entities.Filing.Folder>();
            foreach (var subFolderRecord in folderRecord.Folders){
                Entities.Filing.Folder folder = new Entities.Filing.Folder();
                folder.Id = subFolderRecord.FolderId;
                folder.Name = subFolderRecord.Name;
                folder.Folders = this.GetFolderChildren(subFolderRecord);                
                folder.Activities = this.GetVisionActivities(subFolderRecord.FolderId);
                folder.Documents = this.GetVisionDocuments(subFolderRecord.FolderId);                
                folders.Add(folder);
            }
            return folders;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="folderId"></param>
        /// <returns></returns>
        public List<Entities.Activities.VisionActivity> GetVisionActivities(int folderId)
        {
            List<Entities.Activities.VisionActivity> activityList = new List<Entities.Activities.VisionActivity>();
            foreach (var item in (from a in this.DataAccess.Activities where a.FolderId == folderId select a)){
                activityList.Add(Util.ActivityRecordToEnterpriseActivity(item, false));
            }                        
            return activityList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="folderId"></param>
        /// <returns></returns>
        public List<Entities.Filing.Document> GetVisionDocuments(int folderId)
        {
            List<Entities.Filing.Document> documentList = new List<Entities.Filing.Document>();
            foreach (var item in (from a in this.DataAccess.Documents where a.FolderId == folderId select a)){
                documentList.Add(Util.DocumentRecordToDocument(item, false));    
            }
            return documentList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="activityId"></param>
        /// <returns></returns>
        public Entities.Activities.VisionActivity GetVisionActivityFromCatalog(int activityId)
        {            
            Entities.DataAccess.Activity activityRecord = (from a in this.DataAccess.Activities where a.ActivityId == activityId select a).Single();
            return Util.ActivityRecordToEnterpriseActivity(activityRecord, true);
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="activityKey"></param>
        /// <returns></returns>
        public Entities.Activities.VisionActivity GetVisionActivityFromCatalog(Guid activityKey)
        {
            Entities.DataAccess.Activity activityRecord = this.DataAccess.Activities.SingleOrDefault(a => a.Key == activityKey);
            return Util.ActivityRecordToEnterpriseActivity(activityRecord, true);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="enterpriseActivity"></param>
        public void SaveVisionActivityToCatalog(Entities.Activities.VisionActivity enterpriseActivity)
        {
            DateTime timeStamp = DateTime.Now;
            
            int count = (from a in this.DataAccess.Activities where a.Key == enterpriseActivity.Key select a).Count();
            if (count > 0){
                Entities.DataAccess.Activity activityRecord = (from a in this.DataAccess.Activities where a.Key == enterpriseActivity.Key select a).Single();
                activityRecord.Key = enterpriseActivity.Key;
                activityRecord.Name = enterpriseActivity.Name;
                activityRecord.Description = enterpriseActivity.Description;
                activityRecord.Data = enterpriseActivity.Activity;
                activityRecord.Modified = timeStamp;
                activityRecord.FolderId = enterpriseActivity.FolderId;                                
                this.DataAccess.SubmitChanges();
            }
            else{
                Entities.DataAccess.Activity activityRecord = new Entities.DataAccess.Activity();
                activityRecord.Key = enterpriseActivity.Key;
                activityRecord.Name = enterpriseActivity.Name;
                activityRecord.Description = enterpriseActivity.Description;
                activityRecord.Data = enterpriseActivity.Activity;
                activityRecord.Created = timeStamp;
                activityRecord.Modified = timeStamp;
                activityRecord.FolderId = enterpriseActivity.FolderId;                
                this.DataAccess.Activities.InsertOnSubmit(activityRecord);
                this.DataAccess.SubmitChanges();
            }            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="activityId"></param>
        /// <param name="activityHistroyEvent"></param>
        /// <param name="activityHistroyEventData"></param>
        public void AddActivityHistoryItem(Entities.Activities.ActivityHistoryItem historyItem)
        {
            Entities.DataAccess.ActivityHistory activityHistory = new Entities.DataAccess.ActivityHistory();
            activityHistory.ActivityId = historyItem.ActivityId;
            activityHistory.EventId = (int)historyItem.Event;
            activityHistory.EventData = historyItem.Data;
            activityHistory.EventDate = historyItem.Date;
            this.DataAccess.ActivityHistories.InsertOnSubmit(activityHistory);
            this.DataAccess.SubmitChanges();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="activityId"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        public List<Entities.Activities.ActivityHistoryItem> GetActivityHistoryItems(int activityId, DateTime startDate, DateTime endDate)
        {
            List<Entities.Activities.ActivityHistoryItem> historyItems = new List<Entities.Activities.ActivityHistoryItem>();
            foreach (var item in this.DataAccess.ActivityHistories.Where(ah => ah.ActivityId == activityId && ah.EventDate >= startDate && ah.EventDate <= endDate)){
                historyItems.Add(new Entities.Activities.ActivityHistoryItem() { 
                    ActivityId = item.ActivityId,
                    Event = (Entities.Activities.ActivityHistoryEvent) item.EventId,
                    Data = item.EventData,
                    Date = item.EventDate
                });
            }
            return historyItems;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="documentKey"></param>
        /// <returns></returns>
        public Entities.Filing.Document GetVisionDocumentFromCatalog(Guid documentKey)
        {
            Entities.DataAccess.Document documentRecord = this.DataAccess.Documents.SingleOrDefault(a => a.Key == documentKey);
            return Util.DocumentRecordToDocument(documentRecord, true);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="document"></param>
        public void SaveVisionDocumentToCatalog(Entities.Filing.Document document)
        {
            DateTime timeStamp = DateTime.Now;
            int count = (from a in this.DataAccess.Documents where a.Key == document.Key select a).Count();
            if (count > 0){
                Entities.DataAccess.Document documentRecord = (from a in this.DataAccess.Documents where a.Key == document.Key select a).Single();
                documentRecord.FolderId = document.FolderId;
                documentRecord.Name = document.Name;
                documentRecord.Description = document.Description;
                documentRecord.Data = document.Data;
                documentRecord.Modified = timeStamp;
                this.DataAccess.SubmitChanges();
            }
            else{
                Entities.DataAccess.Document documentRecord = new Entities.DataAccess.Document();
                documentRecord.DocumentId = document.Id;
                documentRecord.FolderId = document.FolderId;
                documentRecord.Key = document.Key;
                documentRecord.Name = document.Name;
                documentRecord.Description = document.Description;
                documentRecord.Data = document.Data;
                documentRecord.Created = timeStamp;
                documentRecord.Modified = timeStamp;
                this.DataAccess.Documents.InsertOnSubmit(documentRecord);
                this.DataAccess.SubmitChanges();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            this.DataAccess.Dispose();           
        }

        /// <summary>
        /// 
        /// </summary>
        internal static class Util
        {
            /// <summary>
            /// 
            /// </summary>
            /// <param name="activityRecord"></param>
            /// <returns></returns>
            public static Entities.Activities.VisionActivity ActivityRecordToEnterpriseActivity(Entities.DataAccess.Activity activityRecord, bool includeActivity)
            {
                Entities.Activities.VisionActivity enterpriseActivity = null;
                if (activityRecord != null){
                    enterpriseActivity = new Entities.Activities.VisionActivity();
                    enterpriseActivity.Id = activityRecord.ActivityId;
                    enterpriseActivity.Key = activityRecord.Key;
                    enterpriseActivity.Name = activityRecord.Name;
                    enterpriseActivity.Description = activityRecord.Description;
                    enterpriseActivity.Created = activityRecord.Created;
                    enterpriseActivity.Modified = activityRecord.Modified;
                    enterpriseActivity.FolderId = 0;
                    enterpriseActivity.FolderPath = string.Empty;
                    
                    if (activityRecord.FolderId != null){
                        enterpriseActivity.FolderId = activityRecord.FolderId.Value;
                    }

                    if (includeActivity){
                        enterpriseActivity.Activity = activityRecord.Data;
                    }
                }
                return enterpriseActivity;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="documentRecord"></param>
            /// <returns></returns>
            public static Entities.Filing.Document DocumentRecordToDocument(Entities.DataAccess.Document documentRecord, bool includeDocument)
            {
                Entities.Filing.Document document = null;
                if (documentRecord != null){
                    document = new Entities.Filing.Document();
                    document.Id = documentRecord.DocumentId;                    
                    document.FolderPath = string.Empty;
                    document.Key = documentRecord.Key;
                    document.Name = documentRecord.Name;
                    document.Description = documentRecord.Description;
                    document.Created = documentRecord.Created;
                    document.Modified = documentRecord.Modified;
                    
                    document.FolderId = 0;
                    if (documentRecord.FolderId != null){
                        document.FolderId = documentRecord.FolderId.Value;
                    }

                    if (includeDocument){
                        document.Data = documentRecord.Data.ToArray();
                    }
                }
                return document;
            }
        }        
    }
}
